import Cesium, { Viewer, Cartesian3, Cartesian2, Scene, Camera } from 'cesium';
import { Coord } from './Coord';

type PopPosition = 'default' | 'leftbottom' | 'leftmiddle';

export interface PopupOptions {
  element: HTMLElement;
  position?: Cartesian3;
  popPosition?: PopPosition;
  visibleMaxCameraHeight?: number;
  renderInViewBounds?: boolean;
}

export class Popup {
  private viewer: Viewer;
  private element: HTMLElement;
  private options: PopupOptions;
  private cameraMoveEnd?: Cesium.Event.RemoveCallback;
  private moving: boolean = false;
  private postRender?: Cesium.Event.RemoveCallback;
  private coord: Coord;
  private scene: Scene;
  private camera: Camera;

  constructor(viewer: Viewer, options: PopupOptions) {
    this.viewer = viewer;
    this.scene = viewer.scene;
    this.camera = viewer.camera;
    this.coord = new Coord(viewer);
    this.options = options;
    this.element = options.element;
    this.addCameraListener();
    this.addMapListener();
  }

  /**
   * 设置弹窗位置
   * @param position 世界坐标
   */
  setPosition(position: Cartesian3): void {
    if (!position) return;

    const screenPosition: Cartesian2 | undefined = this.coord.cartesian3ToCartesian2(position);
    if (!screenPosition) return;

    const { element } = this;
    if (!element) return;

    // 计算默认位置（居中下方）
    let x: number = screenPosition.x - element.clientWidth + 10;
    let y: number = screenPosition.y - element.clientHeight - 15;

    // 处理不同定位方式
    if (this.options.popPosition) {
      switch (this.options.popPosition) {
        case 'leftbottom':
          x = screenPosition.x;
          y = screenPosition.y - element.clientHeight;
          break;
        case 'leftmiddle':
          x = screenPosition.x + 20;
          y = screenPosition.y - element.clientHeight / 2;
          break;
      }
    }

    // 应用样式
    element.style.display = 'block';
    element.style.left = `${x}px`;
    element.style.top = `${y}px`;

    // 更新位置记录
    this.options.position = position;
  }

  /**
   * 添加相机高度监听
   */
  private addCameraListener(): void {
    if (this.options.visibleMaxCameraHeight) {
      this.cameraMoveEnd = this.viewer.camera.moveEnd.addEventListener(() => {
        const h: number = this.camera.getMagnitude();
        const min: number = 6375000; // 地球半径近似值

        if (h - min > this.options.visibleMaxCameraHeight!) {
          this.hide();
        } else {
          this.show();
        }
      });
    }
  }

  /**
   * 隐藏弹窗
   */
  hide(): void {
    if (this.element) {
      this.element.style.visibility = 'hidden';
    }
  }

  /**
   * 显示弹窗
   */
  show(): void {
    if (this.element) {
      this.element.style.visibility = 'visible';
    }
  }

  /**
   * 销毁弹窗
   */
  destroy(): void {
    if (this.cameraMoveEnd) {
      this.cameraMoveEnd();
    }
    if (this.postRender) {
      this.postRender();
    }
  }

  /**
   * 添加地图渲染监听
   */
  private addMapListener(): void {
    this.postRender = this.scene.postRender.addEventListener(() => {
      const position = this.options.position;
      if (!position) return;

      if (this.options.renderInViewBounds) {
        if (this.coord.isVisibleByBounds(position)) {
          if (!this.moving) this.setPosition(position);
          if (this.element.style.visibility !== 'hidden') this.show();
        } else {
          this.hide();
        }
      } else {
        if (!this.moving) this.setPosition(position);
      }
    });
  }
}
